package ar.edu.itba.pod.legajo47573;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import ar.edu.itba.pod.api.Result;
import ar.edu.itba.pod.api.SPNode;
import ar.edu.itba.pod.api.SignalProcessor;
import ar.edu.itba.pod.signal.source.RandomSource;

public class Client {

	private String hostname;
	private int port;
	private SPNode node;
	private SignalProcessor sp;
	
	RandomSource src = new RandomSource(1);

	public Client(String hostname, int port) {
		this.hostname = hostname;
		this.port = port;
	}

	public void startClient() {
		this.waitForCommand();
	}

	public void waitForCommand() {
		try {
			Registry registry = LocateRegistry.getRegistry(hostname, port);
			sp = (SignalProcessor) registry.lookup("SignalProcessor");
			node = (SPNode) registry.lookup("SPNode");
			
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			printOptions();
			while (true) {
				String line = in.readLine().toLowerCase();
				long start = System.nanoTime();
				if(line.equals("0")){
					node.join(Server.clusterName);
				}
				else if (line.equals("1")) {
					node.exit();
					System.out.println("Exited from cluster");
				} else if (line.equals("2")) {
					node.getStats().print(System.out);
				} else if (line.equals("3")) {
					Result results = sp.findSimilarTo(src.next());
					System.out.println(">>> Result: " + results);
				} else if (line.equals("4")) {
					this.generate(sp, 1);
				} else if (line.equals("5")) {
					this.generate(sp, 10);
				} else if (line.equals("6")) {
					this.generate(sp, 100);
				} else if (line.equals("7")) {
					this.generate(sp, 1000);
				} else if (line.equals("8")) {
					this.generate(sp, 50000);
				} else if (line.equals("9")) {
					this.generate(sp, 100000);
				} else if (line.equals("10")) {
					this.generate(sp, 1000000);
				} else if (line.equals("0")) {
					return;
				} else {
					System.out.println("Invalid option");
					printOptions();
					continue;
				}
				long end = System.nanoTime();
				System.out.println(">>> elapsed time: " + ((end - start) / 1000000000.0) + " seconds");
			}
		} catch (Exception e) {
			System.out.println("Unable to connect to node");
			e.printStackTrace();
		}
	}

	private void generate(SignalProcessor sp, int amount)
			throws RemoteException {
		for (int i = 0; i < amount; i++) {
			sp.add(src.next());
		}
	}

	private void printOptions() {
		/*
		 * All this operations are local to the node. When adding a signal the
		 * local add method from the node is called. The local add method
		 * implementation then takes a random node from the cluster and calls
		 * his add method with RMI. The RMI add method adds the signal locally
		 * to the node
		 */
		System.out.println("Options:");
		System.out.println("1 - Exit node from cluster");
		System.out.println("2 - Print stats");
		System.out.println("3 - Process signal for matches");
		System.out.println("4 - Add 1 signal");
		System.out.println("5 - Add 10 signals");
		System.out.println("6 - Add 100 signals");
		System.out.println("7 - Add 1.000 signals");
		System.out.println("8 - Add 50.000 signals");
		System.out.println("9 - Add 100.000 signals");
		System.out.println("10 - Add 1.000.000 signals");
		System.out.println("0 - End");
		System.out.print("> ");
		System.out.flush();
	}

	public static void main(String[] args) throws RemoteException,
			NotBoundException {
		if (args.length < 2) {
			System.out.println("Command line parameters: Client <remote ip> <remote port>");
			return;
		}
		Client client = new Client(args[0], Integer.parseInt(args[1]));
		client.startClient();
	}

}